import React, {
  createContext,
  MutableRefObject,
  useState,
  useMemo,
  useContext,
  useCallback
} from 'react'
import Toast, { Props } from './index'
import { ToastType, VisibleToastsType, ToastContextType,ToastList } from "./types"

// 创建一个createContext
const ToastContext = createContext<ToastContextType>({
  toastList: {},
  visibleToasts: {},
  setToast: () => { },
  hideToast: () => { },
  hideAll: ()=>{}
});
// 组件调用Context
const CustomToast = () => {
  const { toastList, visibleToasts,hideToast } = useContext(ToastContext)
  const toastListIds = ()=>{
    return Object.keys(visibleToasts) 
  }
  return (<>
    {
      toastListIds().map((id)=>{
        return (<Toast key={id} onChange={()=>hideToast(id)} show={visibleToasts[id]} {...toastList[id]}></Toast>)
      })
    }
    
  </>)
}
// 组件调用Context
export const ToastProvider = ({ children }: { children: any }) => {
  const [toastList, setToastList] = useState<ToastList>({})
  const [visibleToasts, setVisibleToasts] = useState<VisibleToastsType>({});
  const toastIndex = React.useRef(7000);
  const hideToast = useCallback(
    (id: any) => {
      setVisibleToasts((prev)=>{
        return {...prev,[id]:false}
      })
    }, [setVisibleToasts])
  const hideAll = useCallback(()=>{
    setVisibleToasts({})
  },[setVisibleToasts])
  const setToast = useCallback(
    (props: ToastType): number => {
      const {
        id = toastIndex.current++,
        ...rest
      } = props
      setToastList((prev) => {
        return { ...prev,[id]:{
          id,
          ...rest
        } }
      })
      setVisibleToasts((prev) => {
        return { ...prev, [id]: true }
      })
      return id
    },
    [toastList, visibleToasts, hideToast]
  )
  const contextValue = useMemo(() => {
    return {
      toastList,
      visibleToasts,
      setToast,
      hideToast,
      hideAll
    }
  }, [toastList,visibleToasts, setToast, hideToast,hideAll])
  return (
    <ToastContext.Provider value={contextValue}>
      {children}
      <CustomToast></CustomToast>
    </ToastContext.Provider>
  )
}


export const useToast = () => {
  const { setToast, hideToast,hideAll } = React.useContext(
    ToastContext
  );
  const toast = useMemo(
    () => ({
      show: setToast,
      close: hideToast,
      closeAll:hideAll
    }),
    [setToast,hideToast,hideAll]
  );

  return toast;
}

//!这部分和ref相关的
export type IToastService = ReturnType<typeof useToast>;

export const ToastRef = React.createRef<IToastService>() as MutableRefObject<IToastService>;

export const _Toast: IToastService = {
  show: (props: Props) => ToastRef.current?.show(props),
  close: (id: any) => ToastRef.current?.close(id),
  closeAll: () => ToastRef.current?.closeAll(),
  // isActive: (id: any) => ToastRef.current?.isActive(id),
};